﻿//------------------------------------------------------------------
// System Name:    NRemedy
// Component:      NRemedy
// Create by:      Parker Zhou (parkerz@wicresoft.com)
// Create Date:    2012-04-10
//------------------------------------------------------------------
using System;
using BMC.ARSystem;
using System.Text;
using Wicresoft.EKA.CommonExtensions;

namespace Wicresoft.EKA.NRemedy
{
    /// <summary>
    /// AR登录会话对象，可以使用using关键字实例化，ARProxy和ARSet两大入口都需要该对象作为会话来访问AR
    /// 
    /// </summary>
    public class ARLoginContext : IDisposable
    {

        private string _server;
        private string _user;
        private string _password;
        private string _authentication;
        private ARLoginStatus _loginStatus;
        private IARServer _serverInstance;
        private Object _lockObject;
        private bool _isARServerReleased = false;


        public bool IsARServerReleased
        {
            get
            {
                return this._isARServerReleased;
            }
            set
            {
                this._isARServerReleased = value;
            }
        }

        public string Server { get { return _server; } }

        public string User { get { return _user; } }

        public string Password { get { return _password; } }

        public string Authentication { get { return _authentication; } }

        private IARServerFactory _factory;

        public bool IsFactoryWithPool { get { return this._factory.IsPooled; } }

        public ARLoginStatus LoginStatus { get { return _loginStatus; } }

        /// <summary>
        /// 可使用该接口来访问BMC.ARSystem的API
        /// </summary>
        public IARServer ServerInstance
        {
            get
            {
                lock (_lockObject)
                {
                    Login();
                    return _serverInstance;
                }
            }
        }

        public Server BMCServer
        {
            get
            {
                return ServerInstance.BMCServer;
            }
        }

        public void BeginBulkEntryTransaction()
        {
            ServerInstance.BMCServer.BeginBulkEntryTransaction();
        }

        public void SendBulkEntryTransaction()
        {
            ServerInstance.BMCServer.SendBulkEntryTransaction();
        }

        public void CancelBulkEntryTransaction()
        {
            ServerInstance.BMCServer.CancelBulkEntryTransaction();
        }

        /// <summary>
        /// Constructor 1  我认为应该通过ARLoginContext 管理  IARServerDefaultFactory 而不是ARProxy。
        /// 因为 ARProxy -》ARLoginContext-》IARServerDefaultFactory-》ARServer 的层级关系。不能越级。
        /// </summary>
        public ARLoginContext(string server, string user, string password, IARServerFactory factory, string authentication = null)
        {
            _lockObject = new Object();
            _factory = factory;
            Init(server, user, password, authentication);
        }
        /// <summary>
        /// Constructor 2
        /// </summary>
        /// <param name="server">Server</param>
        /// <param name="user">User</param>
        /// <param name="password">Password</param>
        public ARLoginContext(string server, string user, string password, string authentication = null) :
            this(server, user, password, ARServerFactoryWithPool.Instance, authentication)
        {
        }

        /// <summary>
        /// Init the server
        /// </summary>
        /// <param name="server">Server</param>
        /// <param name="user">User</param>
        /// <param name="password">Password</param>
        /// <param name="authentication">Authentication</param>
        private void Init(string server, string user, string password, string authentication)
        {
            _server = server;
            _user = user;
            _password = password;
            _authentication = authentication;
        }

        /// <summary>
        /// LogIn IARServer
        /// </summary>
        private void Login()
        {

            if (_loginStatus != ARLoginStatus.Success || _serverInstance == null || _isARServerReleased)
            {

                if (!IsMinimunParameter()) throw new InvalidOperationException("Parameter(Server,User,Password) Is All Necessary");

                IARServer server = null;
                bool isContain = true;
                if (_factory.IsPooled)
                {
                    string poolKey = "Server:" + Server + "User:" + User;
                    isContain = ((IARServerFactoryWithPool)_factory).ContainsKey(poolKey);
                    server = _factory.GetARServer(poolKey);

                    if (isContain)
                    {
                        if (!server.ServerAlive)
                        {
                            try
                            {
                                server.ReLogin();
                                if (!server.ServerAlive) throw new Exception("Server Error in the ReLogin");
                                _loginStatus = ARLoginStatus.Success;
                            }
                            catch (Exception are)
                            {
                                _loginStatus = ARLoginStatus.Failed;
                                throw;
                            }
                        }
                        //此时已经无效应该如何处理。由于Session时间过长，arserver 会话会不会失效。
                    }
                }
                else
                {
                    server = _factory.CreateARServer();
                }

                if ((_factory.IsPooled && !isContain) || !_factory.IsPooled)
                {
                    try
                    {
                        DoLoginARServer(server);
                        _loginStatus = ARLoginStatus.Success;
                    }
                    catch (Exception are)
                    {
                        _loginStatus = ARLoginStatus.Failed;
                        throw;
                    }
                }
                _serverInstance = server;
                _serverInstance.ContextContainer = this;
                _isARServerReleased = false;
            }
        }

        private void DoLoginARServer(IARServer server)
        {
            server.Login(Server, User, Password, Authentication);
            if (!server.ServerAlive)
            {
                throw new Exception("Log in the ARServer Failed.");
            }
        }


        ~ARLoginContext()
        {
            Dispose();
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (ServerInstance != null && !ServerInstance.IsInPool)
                ServerInstance.Logout();
        }

        /// <summary>
        /// does have the enough parameters
        /// </summary>
        /// <returns></returns>
        public bool IsMinimunParameter()
        {
            return (!string.IsNullOrWhiteSpace(Server)
                 && !string.IsNullOrWhiteSpace(User)
                 && !string.IsNullOrWhiteSpace(Password));
        }
    }

}
